#include "StdAfx.h"
#include "Player.h"

Player::Player(void) : block(NULL), m_Dir(0.0f, 0.0f, 0.0f), m_fAngle(0.0f), m_fTurnSpd(0.2f), m_fMovSpd(2.0f)
{
	Load("data/Lamborghini.x");
}


Player::~Player(void)
{
	if (block != NULL) delete block;
	if (meshMaterials != NULL)  delete[] meshMaterials;
	if (m_mesh != NULL)
	m_mesh->Release();
}

void Player::setSpeed(float spd)
{
	m_fMovSpd = spd;
}

bool Player::Load(char * filename)
{
	LPD3DXBUFFER materialBuffer;

	// Load the mesh from the specified file
	D3DXLoadMeshFromX(filename, D3DXMESH_MANAGED, 
							 block->md3dDev, NULL, 
                             &materialBuffer,NULL, 
							 &numMaterials, 
                             &m_mesh );
	D3DXMATERIAL* d3dxMaterials = (D3DXMATERIAL*)materialBuffer->GetBufferPointer();

	meshMaterials = new D3DMATERIAL9[numMaterials];
	meshTextures  = new LPDIRECT3DTEXTURE9[numMaterials];

	for (DWORD i=0; i<numMaterials; i++)
	{
		meshMaterials[i] = d3dxMaterials[i].MatD3D; // Copy the material
		meshMaterials[i].Ambient = meshMaterials[i].Diffuse; // Set the ambient color for the material (D3DX does not do this)
     
		// Create the texture if it exists - it may not
		meshTextures[i] = NULL;
		if (d3dxMaterials[i].pTextureFilename)
		{
			char texturefile[256];
			strcpy(texturefile, "data/");
			strcat(texturefile, d3dxMaterials[i].pTextureFilename);
			D3DXCreateTextureFromFile(block->md3dDev, texturefile, &meshTextures[i]);
		}
	}

	materialBuffer->Release();
	materialBuffer = NULL;
	return true;
}

bool Player::Collides(const D3DXVECTOR3 pt, float radius)
{
	float distSQ = (pt.x - block->m_Pos.x)*(pt.x - block->m_Pos.x) + (pt.z - block->m_Pos.z) * (pt.z - block->m_Pos.z);
	return distSQ < (radius*radius);
}

void Player::RotateMesh(const D3DXVECTOR3 direction)
{
	if (direction.z > 0.0f && (direction.x == 0.0f)) m_fAngle = D3DXToRadian(90.0f);
	else if (direction.z < 0.0f && (direction.x == 0.0f)) m_fAngle = D3DXToRadian(270.0f);
	else if (direction.x > 0.0f && (direction.z == 0.0f)) m_fAngle = D3DXToRadian(180.0f);
	else if (direction.x < 0.0f && (direction.z == 0.0f)) m_fAngle = D3DXToRadian(0.0f);

	else if (direction.x > 0.0f && (direction.z > 0.0f)) m_fAngle = D3DXToRadian(135.0f);
	else if (direction.x < 0.0f && (direction.z < 0.0f)) m_fAngle = D3DXToRadian(315.0f);
	else if (direction.x > 0.0f && (direction.z < 0.0f)) m_fAngle = D3DXToRadian(225.0f);
	else if (direction.x < 0.0f && (direction.z > 0.0f)) m_fAngle = D3DXToRadian(45.0f);
}

const D3DXVECTOR3 Player::getForwardDirection()
{
	float x = m_fMovSpd*sin(m_fAngle);
	float z = m_fMovSpd*cos(m_fAngle);
	return D3DXVECTOR3(x, 0, z);
}

void Player::moveForward(bool boosted)
{
	float spd = boosted? m_fMovSpd*2.0f : m_fMovSpd;
	float x = spd*sin(m_fAngle);
	float z = spd*cos(m_fAngle);
	block->Last_m_Pos = block->m_Pos;
	block->m_Pos += D3DXVECTOR3(x, 0, z);
	camera.move(D3DXVECTOR3(x, 0, z), D3DXVECTOR3(1.0f, 0, 1.0f));
}

void Player::moveBackward(bool boosted)
{
	float spd = boosted? m_fMovSpd*2.0f : m_fMovSpd;
	float x = spd*sin(m_fAngle);
	float z = spd*cos(m_fAngle);
	block->Last_m_Pos = block->m_Pos;
	block->m_Pos -= D3DXVECTOR3(x, 0, z);
	camera.move(D3DXVECTOR3(-x, 0, -z), D3DXVECTOR3(1.0f, 0, 1.0f));
}

void Player::turnLeft()
{
	m_fAngle -= m_fTurnSpd;
}

void Player::turnRight()
{
	m_fAngle += m_fTurnSpd;
}

HRESULT Player::Render()
{
	if (camera.isTopDown())
	{
		for (DWORD i=0; i<numMaterials; i++)
		{
			// Set the material and texture for this subset
			Block::md3dDev->SetMaterial(&meshMaterials[i]);
			Block::md3dDev->SetTexture(0, meshTextures[i]);
        
			// apply the rotations
			D3DXMATRIX rotation;
			D3DXMatrixIdentity(&rotation);
			D3DXMatrixRotationY(&rotation, m_fAngle);

			// move the mesh
			D3DXMATRIX translate;
			D3DXMatrixIdentity(&translate);
			translate(3, 0) = block->m_Pos.x;
			translate(3, 1) = 0.0f; //block->m_Pos.y;
			translate(3, 2) = block->m_Pos.z;

			//translate(3, 0) = pos.x;
			//translate(3, 1) = 0.0f; // always ignore the y coord, it is not needed
			//translate(3, 2) = pos.z;

			D3DXMATRIX worldMat;
			D3DXMatrixIdentity(&worldMat);
			worldMat = rotation * translate;

			block->md3dDev->SetTransform(D3DTS_WORLD, &worldMat);

			// draw the mesh subset
			m_mesh->DrawSubset( i );
			block->md3dDev->EndScene();
			block->md3dDev->Present(NULL, NULL, NULL, NULL);
		}
	}
	return true;
}



